HTML5 Canvas绘图笔记(2)

绘制图像

引入图像到canvas里需要以下两步基本操作:
-获得一个指向HTMLImageElement的对象或者另一个canvas元素的引用作为源,也可以通过提供一个URL的方式来使用图片
-使用drawImage()函数将图片绘制到画布上

获得需要绘制的图片

有几种方式可以获取到我们需要在canvas上使用的图片。

由零开始创建图像

1、新建图片对象,并将其src属性设置为图片路径。

1
2
var img = new Image();   // 创建一个img元素
img.src = 'myImage.png'; // 设置图片源地址

2、将绘制代码放在img.onload中,让绘制在图片加载完后执行.

1
2
3
4
var img = new Image();   // 创建img元素
img.onload = function(){
context.drawImage(img,50,50);// 执行drawImage语句}
img.src = 'myImage.png'; // 设置图片源地址

当脚本执行后,图片开始装载。若调用 drawImage 时,图片没装载完,那什么都不会发生(在一些旧的浏览器中可能会抛出异常)。因此你应该用load时间来保证不会在加载完毕之前使用这个图片.

使用相同页面内的图片

通过下列方法的一种来获得与canvas相同页面内的图片的引用:
-document.images集合
-document.getElementsByTagName()方法

  • document.getElementById() //通过图片ID获得这个图片
使用其它 canvas 元素

和引用页面内的图片类似地,用 document.getElementsByTagName 或 document.getElementById 方法来获取其它 canvas 元素。但你引入的应该是已经准备好的 canvas。
一个常用的应用就是将第二个canvas作为另一个大的 canvas 的缩略图。

通过 data: url 方式嵌入图像

Data urls 允许用一串 Base64 编码的字符串的方式来定义一个图片。
var img_src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';
其优点就是图片内容即时可用,无须再到服务器兜一圈。(还有一个优点是,可以将 CSS,JavaScript,HTML 和 图片全部封装在一起,迁移起来十分方便。)
缺点就是图像没法缓存,图片大的话内嵌的 url 数据会相当的长.

绘制图片

一旦获得了源图对象,我们就可以使用 drawImage 方法将它渲染到 canvas 里。drawImage 方法有三种形态.

drawImage(image, x, y)

其中image为图片对象名称,x 和 y 为绘图位置(图片左上角在画布中的坐标).

1
2
3
4
5
6
7
8
//画布300*300,图片200*200
var img = new Image();
img.src = "http://img3.imgtn.bdimg.com/it/u=1011179444,2282576107&fm=21&gp=0.jpg";

context.beginPath();
img.onload = function () {
context.drawImage(img,50,50);
}

drawImage(image, x, y, width, height):
  • x和y :绘图位置(图片左上角在画布中的坐标)
  • width和height:自定义图片在canvas中显示的大小
    1
    2
    3
    4
    5
    6
    7
    8
    //画布300*300,图片200*200
    var img = new Image();
    img.src = "http://img3.imgtn.bdimg.com/it/u=1011179444,2282576107&fm=21&gp=0.jpg";

    context.beginPath();
    img.onload = function () {
    context.drawImage(img,0,0,300,300);
    }
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight):

选取图像的一部分矩形区域进行绘制.

  • sx:图像上的x坐标
  • sy:图像上的y坐标
  • sWidth:矩形区域的宽度
  • sHeight:矩形区域的高度
  • dx:画在canvas的x坐标
  • dy:画在canvas的y坐标
  • dWidth:画出来的宽度
  • dHeight:画出来的高度
    前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。
    7

图像裁剪c ontext.clip()

context.clip()只绘制封闭路径区域内的图像,不绘制路径外部图像,用的时候
先创建裁剪区域,再绘制图像.
如图所示。红边五角星就是裁切路径,所有在路径以外的部分都不会在 canvas 上绘制出来。
9

1
2


图片像素处理

获取图片信息(使用图像数据)

getImageData(sx,sy,sw,sh)

  • sx:cavas的x轴坐标点
  • sy:canvas的y轴坐标点
  • sw:距离x的宽度
  • sh:距离y的高度
    var imagedata=context.getImageData(sx,sy,sw,sh)
    这里返回的对象是ImageData的实例。每个ImageData对象都有三个属性:width/height/data.
    data
    data属性是一个数组,保存着图像中每一个像素的数据。在data数组中,每一个像素用4个元素来保存,分别表示红、绿、蓝和透明度值。也就是[r1,g1,b1,a1,r2,g2,b2,a2,r3,g3,b3,a3…]这样一直排列下去.
    数组的长度length = w h 4
    在循环数组获取每个元素的时候,一般是要让i+=4这样获取每个像素
    data数组中每个元素的值大小:0-255.

设置像素颜色:

context.putImageData(imagedata,dx,dy,dirtyX,dirtyY,dirtyWidth,dirtyHeight)
对imagedata数组中的各个像素的r、g、b、a值进行修改,再调用putImageData方法进行绘制

  • imagedata:修改后的imagedata
  • dx:重绘图像的起点横坐标(重绘的起点和原来的图像一致的话就会把原来的图形覆盖掉,看起来就像是原来的图像变成现在的图像一样)
  • dy:重绘图像的起点纵坐标
  • //以下可选参数,设置重绘的矩形范围,如果缺省,默认会重绘所有的imegedata
    – dirtyX:矩形左上角x轴坐标
    – dirtyY:矩形左上角y轴坐标
    – dirtyWidth:矩形长度
    – dirtyHeight:矩形高度
灰度效果

在rgba表示中,rgb值相同就一定是灰色.
获取每个像素的rgba值并将rgb值改为gray = (r+g+b)/3
重绘像素

1
2
3
4
5
6
7
8
9
10
11
12
13
//灰度处理
var imageData = context.getImageData(0,0,200,200);
var data = imageData.data;
for (var i = 0; i<200*200*4; i+=4){
var r = data[i];
var g = data[i+1];
var b = data[i+2];
var gray = (r+g+b)/3;
data[i] = gray; //r值
data[i+1] = gray; //g值
data[i+2] = gray; //b值
}
context.putImageData(imageData,200,0)

反色效果

在rgba表示中,rgb反色就是用255减去相应的数值
获取每个像素的rgba值并将rgb值改为 data[i] = 255-data[i]
重绘像素

1
2
3
4
5
6
7
8
9
//反色处理
var imageData = context.getImageData(0,0,200,200);
var data = imageData.data;
for (var j = 0; j<200*200*4; j+=4){
data[j] = 255-data[j];
data[j+1] = 255-data[j+1];
data[j+2] = 255-data[j+2];
}
context.putImageData(imageData,0,200);

图形输出

使用toDateURL()方法,可以导出在canvas元素上绘制的图像。
这个方法接受一个参数,即图像的MIME类型格式。

1
2
3
4
5
6
var canvas=document.getElementById("canvas");
...
var imgURI=canvas.toDataURL("image/png");
var img=document.createElement("img");
img.src=imgURI;
document.body.appendChild(img);

图形组合 compositing

context.globalCompositeOperation=type
我们不仅可以在已有图形后面再画新图形,还可以用来遮盖,清除(比 clearRect 方法强劲得多)某些区域。
图形组合就是两个图形相互叠加了图形的表现形式,是后画的覆盖掉先画的呢,还是相互重叠的部分不显示等等,至于怎么显示就取决于type的值了
type:
-source-over(default):这是默认设置,新图形会覆盖在原有内容之上。
-source-in:新图形会仅仅出现与原有内容重叠的部分。其它区域都变成透明的。
-source-out:结果是只有新图形中与原有内容不重叠的部分会被绘制出来。
-source-atop:新图形中与原有内容重叠的部分会被绘制,并覆盖于原有内容之上。
-destination-over:会在原有内容之下绘制新图形。
-destination-in:原有内容中与新图形重叠的部分会被保留,其它区域都变成透明的。
-destination-out:原有内容中与新图形不重叠的部分会被保留。
-destination-atop:原有内容中与新内容重叠的部分会被保留,并会在原有内容之下绘制新图形
-lighter:两图形中重叠部分作加色处理。
-darker:两图形中重叠的部分作减色处理。
-copy:只有新图形会被保留,其它都被清除掉。
-xor:重叠的部分会变成透明。

8
注意:蓝色方块是先绘制的,即“已有的 canvas 内容”,红色圆形是后面绘制,即“新图形”。

参考资源:

  1. canvas学习(二) http://www.jianshu.com/p/65de47ef33d2
  2. 玩转html5<canvas>画图 http://www.cnblogs.com/tim-li/archive/2012/08/06/2580252.html#10
  3. Canvas教程 https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial
坚持原创技术分享,您的支持将鼓励我继续创作!